package com.gpj.sgz.system;

import com.gpj.sgz.init.base.General;
import com.gpj.sgz.init.base.Skill;
import com.gpj.sgz.init.skill.Attack;
import com.gpj.sgz.untils.Constants;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * @className BattleGround
 * @description TODO
 * @author GPJ
 * @date 2020/10/1 9:50
 * @version 1.0
 **/
@Slf4j
public class BattleGround {
	private static final String SEPARATE_SYMBOL = "-----------";

	private Army selfArmise; // 我方部队
	private Army enemyArmise; // 我方部队
	private List<General> orders = new ArrayList<>(); // 排序
	private List<General> fails = new ArrayList<>(); // 失败武将
	private Map<String, General> aim = new HashMap<>(); // 目标
	private Skill attack = new Attack();

	public BattleGround(Army ourArmise, Army enemyArmise) {
		this.selfArmise = ourArmise;
		this.enemyArmise = enemyArmise;
		orders.addAll(selfArmise.getGenerals());
		orders.addAll(enemyArmise.getGenerals());
	}

	public void fight(){
		int num = 1;
		boolean reuslt = true;
		while (reuslt){
			log.info("{} 第{}回合 {}", SEPARATE_SYMBOL, num++, SEPARATE_SYMBOL);
			prepare();
			reuslt = orders.stream().allMatch(
					general -> doFight(general, aim.get(general.getId()))
			);
		}
	}
	
	private void prepare(){
		orders.sort((o1, o2) -> o1.getSpeed() - o2.getSpeed() > 0?1:-1);

		doAim(selfArmise.getGenerals(), enemyArmise.getGenerals(), enemyArmise.getMainGeneral());
		doAim(enemyArmise.getGenerals(), selfArmise.getGenerals(), selfArmise.getMainGeneral());
	}
	
	private void doAim(List<General> sourceGenerals, List<General> targetGenerals, General mainGeneral){
		for (int i = 0; i < sourceGenerals.size(); i++) {

			if(targetGenerals.size() <= i){
				aim.put(sourceGenerals.get(i).getId(), mainGeneral);
			}else{
				General general = targetGenerals.get(i);
				aim.put(sourceGenerals.get(i).getId(), fails.contains(general)?mainGeneral:general);
			}
		}
	}
	
	private boolean doFight(General sourceGeneral, General targetGeneral){
		log.info("[{}]开始行动", sourceGeneral.getName());

		attack.handle(sourceGeneral, targetGeneral, this);
		if(targetGeneral.getArms() <= 0){
			log.info("{}[{}]兵力为0，无法继续行动", Constants.LOG_TAB, targetGeneral.getName());
			fails.add(targetGeneral);
			return !isEnd(targetGeneral);
		}
		return true;
	}
	
	private boolean isEnd(General general){
		if(general.getArms() <= 0){
			if(general == selfArmise.getMainGeneral()) {
				log.info("我方主将[{}]兵力为0，战斗失败", general.getName());
			}else{
				log.info("敌方主将[{}]兵力为0，战斗胜利", general.getName());
			}
		}
	    return false;
	}
}
